public class CircularArrayLoop {

    public boolean circularArrayLoop1(int[] nums) {
        int n = nums.length;
        if (n == 1) return false;
        for (int i = 0; i < n; i++) {
            int slow = i + nums[i];
            slow = process(n, slow);
            int fast = i + nums[i];
            fast = process(n, fast);
            boolean flag = nums[i] > 0 ? true : false;
            int count = 1;
            for (int j = 0; j < nums.length; j++) {
                if (nums[slow] < 0 && flag) break;
                if (nums[slow] > 0 && !flag) break;
                slow = slow + nums[slow];
                slow = process(n, slow);
                fast = fast + nums[fast];
                fast = process(n, fast);
                if (nums[fast] < 0 && flag) break;
                if (nums[fast] > 0 && !flag) break;
                fast = fast + nums[fast];
                fast = process(n, fast);
                if (nums[fast] < 0 && flag) break;
                if (nums[fast] > 0 && !flag) break;
                if (fast == slow) break;
                ++count;
            }
            int temp = slow + nums[slow];
            temp = process(n, temp);
            if (fast == slow && count > 1 && slow != temp) return true;
        }
        return false;
    }

    public int process(int n, int target) {
        if (target < 0) return n + (target % n);
        if (target >= n) return target % n;
        return target;
    }

    public boolean circularArrayLoop(int[] nums) {
        if (nums.length == 1) return false;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == 0) continue;
            int slow = i;
            int fast = process1(nums, slow);
            while (nums[slow] * nums[fast] > 0 && nums[slow] * nums[process1(nums, fast)] > 0) {
                if (slow == fast) {
                    if (slow != process1(nums, slow)) {
                        return true;
                    } else break;
                }
                slow = process1(nums, slow);
                fast = process1(nums, process1(nums, fast));
            }
            int add = i;
            while (nums[add] * nums[process1(nums, add)] > 0) {
                int temp = process1(nums, add);
                nums[add] = 0;
                add = temp;
            }
        }
        return false;
    }

    public int process1(int[] nums, int i) {
        i = nums[i] + i;
        int n = nums.length;
        if (i < 0) return n + (i % n);
        return i % n;
    }
}
